/*
  Ce fichier contient le main produisant l'executable permettant l'analyse de fréquence d'un texte codé grâce à la technique dite de César


  Argument attendu : Chaine de caractère à décrypter. Cette chaine peut être passer directement en argument ou bien être récupérer dans un fichier.
  Il est laissé au soin de Valentin de s'occuper de la partie de gestion des arguments. Nous supposerons pour le moment qu'elle est passée en argument
  dans argv[1].
*/


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "header.h"




int main(int argc, char** argv)
{

  if (argc != 3)
    {
      fprintf(stderr,"Erreur, nombre de paramètres incorrect.\n\n");
      usage_freqC();
      exit(1);
    }
  
  
  int i = 0; //variable de boucle
  int* flags = (int*) malloc(sizeof(int)*2);
  for (i=0;i<2;i++)
    flags[i]=0;  
  // flags[0] --> texte vient de la ligne de c?
  // flags[1] --> texte vient d'un fichier?
  
  char* text;
  
  
  
  traitement_freqC(argv,&text,&flags);
  
  
 
  if ((flags[0]==0) && (flags[1]==0))
    {
      fprintf(stderr,"Erreur,Pas de texte crypté fourni pour 'frequenceCesar'.\n\n");
      usage_freqC();
      exit(2);
    }
  
  
  if (flags[0]==1)
    text=argv[2];
  
 
  
  
 

  int* texte =string_to_int(text); //Texte à decrypter
  int taille = nombre_caracteres_valides(text);  //Taille du texte à décrypter
  /* if(flags[1]==1) // décrémentation, car texte vient du fichier et de la fonction extract où on rajoute à la fin de la chaine un '\n' de fin de chaine, donc la taille exacte est strlen(text)-1 dans ce cas là
     taille--;
  */


  if( system("clear") == -1)
    {
      fprintf(stderr, "Erreur dans le clear\n");
    }

 

  int d;
  float* freqP = (float*) malloc (sizeof(float)*MAX_NUMBER_OF_CHILDREN); //Tableau des frequences des lettres simples
  float* freqP_b = (float*) malloc (sizeof(float)*MAX_NUMBER_OF_CHILDREN); // Tableau des fréquences des bigrammes
  frequencies(texte, taille, freqP, freqP_b); //Rempli les tableaux avec les valeurs mesurées dans texte
  int choix;
  Tree* current = create();
  print_tree(*current, texte, taille, stdout);
  unsigned char stop = 0;
  while(! stop)
    {
      printf("Que souhaitez-vous faire ?\n0 : Proposer une correspondance\n1 : Demander une proposition\n2 : Revenir en arriere\n3 : Afficher les fils\n4 : Accèder à un fils\n5 : Quitter le programme\n");
      if(scanf("%d", &choix) == EOF)
	{
	  fprintf(stderr, "Erreur dans le scanf\n");
	}
 
      if (choix != '\n') // vidage du buffer stdin pour enchainer correctement les scanf;
	{ 
	  while ((d = getchar ()) != '\n' && d != EOF) 
	    { 

	    } 
	}


      switch(choix)
	{
	case 0 : 
	  {
	    char c;
	    int valid = 0;
	    int prop = next_proposition(freqP, (*current).id);
	    int cor = -1;
	    while(!valid)
	      {
		printf("Nous étudions la lettre %c (frequence dans le texte : %.2f%%).\n",int_to_char(prop, 0), freqP[prop]);
		printf("Rappel des lettres déjà utilisées :\n");
		print_id(*current);
		printf("Veuillez entrer votre proposition de décryptage ($ pour sortir de la boucle):\n"); 
	
		if(scanf("%c", &c) == EOF)
		  {
		    fprintf(stderr, "Erreur dans le scanf\n");
		  }
 
		if (c != '\n') // vidage du buffer stdin pour enchainer correctement les scanf;
		  { 
		    while ((d = getchar ()) != '\n' && d != EOF) 
		      { 
			
		      } 
		  }
		if(c == '$')
		  {
		    break;
		  }
		cor = char_to_int(c);
		/*
		  Test de la proposition. Il faut que :
		  cor ne soit pas déjà utilisé par current
		  que le couple (prop, cor) n'existe dans aucun fils de current
		*/
  		valid = ( (current->id[cor] == -1) && !(exist_in_children(*current, prop, cor)));
		if(!valid)
		  {
		    printf("Votre proposition est invalide. Veuillez proposer une autre lettre\n");
		  }
	      }
	    if(valid)
	      {
		current = add_child(current, prop, cor);
	      }
	    printf("Vous êtes à la position : \n");
	    print_path(*current);
	    printf("A cette position, le tableau d'identification est le suivant : \n");
	    print_id(*current);
	    printf("Décryptage en cours : \n");
	    print_tree(*current, texte, taille, stdout);
	    break;
	  }
	case 1 : 
	  {
	    int p1 = next_proposition(freqP, (*current).id);
	    int cor;
	    int bigram = 0;
	    int nb_propositions = 2;
	    int* bigrams = (int*)malloc(2*sizeof(int));
	    if(p1 == -1)
	      {
		fprintf(stderr, "Erreur dans la recherche d'une nouvelle proposition \n");
		break;
	      }
	    if(freqP_b[p1] != 0)
	      {
		bigram = 1; //Il existe au moins un bigramme de la lettre étudiée
	      }
	    int* p2 = identify(current, p1);;
	    if(p2[0] == -1)
	      {
		fprintf(stderr, "Erreur tentative d'identification \n");
		break;
	      }
	    if(p2[1] != -1)
	      {

		if(bigram)
		  {
		    printf("Nous étudions la lettre %c (fréquence d'apparition dans le texte : %.2f%%, fréquence d'apparition du bigramme : %.2f%%). Les meilleurs propositions de correspondance à ce point sont : \n",  int_to_char(p1, 0), freqP[p1], freqP_b[p1]);
		  }
		else
		  {
		    printf("Nous étudions la lettre %c (frequence d'apparition dans le texte : %.2f%%). Les deux meilleurs propositions de correspondance à ce point sont : \n(1) %c (fréquence dans la langue française : %.2f%%)\n(2) %c (frequence dans la langue française : %.2f%%)\n",  int_to_char(p1, 0), freqP[p1], int_to_char(p2[0], 1), th_frequency(p2[0]), int_to_char(p2[1], 1), th_frequency(p2[1]) );  
		  }
		if(bigram)
		  {
		    next_bigrams(current, p1, bigrams); //retourne les deux meilleurs bigrammes possibles (disponibles et maximaux)
		    ;
		    if(bigrams[0] == -1)
		      {
			fprintf(stderr, "Erreur choix bigrammes. Pas de traitement des bigrammes pour ce tour \n");
			bigram = 0;
			printf("Nous étudions la lettre %c (frequence d'apparition dans le texte : %.2f%%). Les deux meilleurs propositions de correspondance à ce point sont : \n",  int_to_char(p1, 0), freqP[p1]);
		      }
		    else
		      {
			if(exist_match(bigrams, p2))
			  {
			    nb_propositions = match_bigram(p2, bigrams, freqP_b);
			  }
			else //Un bigramme existe mais il n'est pas dans les deux propositions. On propose les deux meilleurs bigrammes et les deux meilleurs propositions
			  {
			    printf("(1) %c (fréquence dans la langue française : %.2f%%)\n(2) %c (frequence dans la langue française : %.2f%%)\n(3) %c (fréquence dans la langue française : %.2f%%, fréquence du bigramme %.2f%%)\n(4) %c (fréquence dans la langue française : %.2f%%, fréquence du bigramme %.2f%%)\n", int_to_char(p2[0], 1), th_frequency(p2[0]), int_to_char(p2[1], 1), th_frequency(p2[1]), int_to_char(bigrams[0], 1), th_frequency(bigrams[0]),  th_frequency_b(bigrams[0]), int_to_char(bigrams[1], 1), th_frequency(bigrams[1]), th_frequency_b(bigrams[1]));
			    nb_propositions = 4;
			  }
			
		      }
		  }
		/*
		  Ce qui nous intéresse maintenant c'est le nb_propositions.
		*/
		unsigned char ok = 0;
		while(!ok)
		  {
		    printf("Quelle proposition souhaitez-vous conserver ?\n");
		    if(scanf("%d", &choix) == EOF)
		      {
			fprintf(stderr, "Erreur dans le scanf\n");
		      }
		    switch(choix)
		      {
		      case 1 : 
			{
			  cor = p2[0];
			  ok = 1;
			  break;
			}
		      case 2 : 
			{
			  cor = p2[1];
			  ok = 1;
			  break;
			}
		      case 3 : 
			{
			  if(nb_propositions >= 3)
			    {
			      if(bigrams[0] != p2[0] && bigrams[0] != p2[1])
				{
				  cor = bigrams[0];
				}
			      else
				{
				  cor = bigrams[1];
				}
			      ok = 1;
			      break;
			    }
			}
		      case 4 :
			{
			  if(nb_propositions >= 4)
			    {
			      cor = bigrams[1];
			      ok = 1;
			      break;
			    }
			}
		      default :
			{
			  printf("Je n'ai pas compris votre réponse, veuillez recommencer svp\n");
			  break;
			}
		      }
		  }
	      }
	    else
	      {
		printf("L'unique solution disponible est :\n %c dans le texte crypté devient %c en clair \n",  int_to_char(p1, 0), int_to_char(p2[0], 1));
		cor = p2[0];
	      }
	    current = add_child(current, p1, cor);

	    printf("Vous êtes à la position : ");
	    print_path(*current);
	    printf("A cette position, le tableau d'identification est le suivant : \n");
	    print_id(*current);
	    printf("Décryptage en cours : \n");
	    print_tree(*current, texte, taille, stdout);
	    break;
	  }
	case 2 : 
	  {
	    current = go_to_parent(current);

	    printf("Vous êtes à la position : \n");
	    print_path(*current);
	    printf("A cette position, le tableau d'identification est le suivant : \n");
	    print_id(*current);
	    printf("Décryptage en cours : \n");
	    print_tree(*current, texte, taille, stdout);
	    break;
	  }
	case 3 : 
	  {
	    if(current->nb_children > 0)
	      {
		for(int i = 0; i < current->nb_children; ++i)
		  {
		    printf("Fils n°%d\n", i);
		    printf("Position : \n");
		    print_path(*current->children[i]);
		    printf("tableau id : \n");
		    print_id(*current->children[i]);
		    printf("Décryptage : \n");     		   
		    print_tree(*current->children[i], texte, taille, stdout);
		    printf("\n\n");
		  }
	      }
	    else
	      {
		printf("Il n'y a aucun fils à cette position\n");
	      }
	    printf("Vous êtes à la position : \n");
	    print_path(*current);
	    printf("A cette position, le tableau d'identification est le suivant : \n");
	    print_id(*current);
	    printf("Décryptage en cours : \n");
	    print_tree(*current, texte, taille, stdout);
	    break;
	  }

	case 4 :
	  {
	    if(current->nb_children > 0)
	      {
		int valid_child = 0;
		while(!valid_child)
		  {
		    printf("Veuillez entrer le numéro du fils que vous souhaitez rejoindre.\nRappel : Il y a un nombre total de %d fils à votre position (numéroté de 0 à %d)\n",current->nb_children, current->nb_children-1);
		    if(scanf("%d", &choix) == EOF)
		      {
			fprintf(stderr, "Erreur dans le scanf\n");
		      }
		    if((choix >= 0) && (choix < current->nb_children))
		      {
			valid_child = 1;
		      }
		    else
		      {
			printf("Le fils n°%d n'existe pas, veuillez recommencer\n", choix);
		      }
		  }
		current = go_to_child(*current, choix);
	      }
	    else
	      {
		printf("Il n'y a pas de fils à cette position !\n");
	      }
	    printf("Vous êtes à la position : \n");
	    print_path(*current);
	    printf("A cette position, le tableau d'identification est le suivant : \n");
	    print_id(*current);
	    printf("Décryptage en cours : \n");
	    print_tree(*current, texte, taille, stdout);
	    break;
	  }
	case 5 :
	  {
	    printf("Fin de l'execution.\nEnregistrement dans le fichier \"frequency_analysis_out\".\nAu revoir. \n");
	    FILE* out = fopen("frequency_analysis_out", "w+");
	    if(out == NULL)
	      {
		fprintf(stderr,"Erreur dans l'ouverture du fichier \"frequency_analysis_out\"\n");
	      }
	    else
	      {
		print_tree(*current, texte, taille, out);
		fclose(out);
	      }
	    stop = 1;
	    break;
	  }
	default : 
	  {
	    printf("Je n'ai pas compris votre choix, recommencez s'il vous plait \n");
	  }
	}
    }
  current = go_to_root(current);
  free(freqP);
  free(freqP_b);
  remove_tree(current);
  free(texte);
  if (flags[1]!=0)
    {
      free(text);
    }
  free(flags);
  return 0;
}
